use sea_orm::{QueryFilter, Set, TransactionTrait};
use sea_orm::ColumnTrait;
use std::error::Error;
use async_trait::async_trait;
use redis::aio::MultiplexedConnection;
use sea_orm::{DatabaseConnection, EntityTrait};
use serde_json::Value;
use crate::entity::{order_main, order_product_r, product_main, sys_scheduled_task};
use crate::scheduler::dynamic_task_scheduler::{DynamicTask, ExecuteResult};
pub struct OrderTimeoutCancellationTask;

#[async_trait]
impl DynamicTask for OrderTimeoutCancellationTask {
    async fn execute(
        &self,
        db: DatabaseConnection,
        conn: MultiplexedConnection,
        task_parameter: Option<String>
    )
        -> Result<ExecuteResult, Box<dyn Error>>
    {
        // 执行任务逻辑
        let timeout_minutes = match task_parameter {
            Some(params) => {
                let v: Value =  serde_json::from_str(params.as_ref())?;

                v.get("timeout_minutes")
                    .and_then(|v| v.as_u64())
                    .unwrap_or(30)
            }
            None => { 30 }
        };

        // 查找超时未支付的订单
        let timeout_threshold = chrono::Utc::now().naive_utc()
            - chrono::Duration::minutes(timeout_minutes as i64);

        let expired_orders = order_main::Entity::find()
            .filter(order_main::Column::Status.eq("non_pay"))
            .filter(order_main::Column::CreateTime.lt(timeout_threshold))
            .all(&db)
            .await?;

        let mut cancelled_count = 0;
        let mut fail_count = 0;
        for order in &expired_orders {
            match cancel_order_if_unpaid(db.clone(), order.clone()).await {
                Ok(cancelled) if cancelled => {
                    cancelled_count += 1;
                    println!("订单 {} 已超时取消", order.id);
                }
                Ok(_) => {
                    // 订单已经处理过，无需操作
                }
                Err(e) => {
                    fail_count += 1;
                    eprintln!("取消订单 {} 失败: {}", order.id, e);
                }
            }
        }



        println!("本次任务共取消 {} 个超时订单", cancelled_count);
        Ok(ExecuteResult {
            code: 0,
            total_count: expired_orders.len() as u32,
            success_count: cancelled_count,
            fail_count: fail_count,
            error_message: None,
        })
    }
}

async fn cancel_order_if_unpaid(
    db: DatabaseConnection,
    order: order_main::Model
) -> Result<bool, Box<dyn Error>> {
    // 如果订单不是未支付状态，则不处理
    if order.status != "non_pay" {
        return Ok(false);
    }

    // 开启事务
    let txn = db.begin().await?;


    // 提前保存 order.id，避免后续 move 后无法访问
    let order_id = order.id;

    // 更新订单状态为已取消
    let mut order_active: order_main::ActiveModel = order.into();
    order_active.status = Set("cancel".to_string());
    order_active.update_time = Set(chrono::Utc::now().naive_utc());

    order_main::Entity::update(order_active)
        .exec(&txn)
        .await?;

    // 查找订单关联的商品
    let order_products = order_product_r::Entity::find()
        .filter(order_product_r::Column::OrderId.eq(order_id))
        .all(&txn)
        .await?;

    // 为每个商品解冻库存
    for order_product in order_products {
        let product = product_main::Entity::find_by_id(order_product.product_id)
            .one(&txn)
            .await?
            .ok_or_else(|| format!("商品不存在: {}", order_product.product_id))?;

        // 解冻库存 (减少冻结数量)
        let mut product_active: product_main::ActiveModel = product.clone().into();
        product_active.stockpile_frozen = Set(product.stockpile_frozen - order_product.quantity);
        product_active.stockpile = Set(product.stockpile + order_product.quantity);
        product_active.update_time = Set(chrono::Utc::now().naive_utc());

        product_main::Entity::update(product_active)
            .exec(&txn)
            .await?;
    }

    // 提交事务
    txn.commit().await?;

    Ok(true)
}